//
//  KNBaseRequest.m
//  Backhome
//
//  Created by kwep_vbn on 2017/3/22.
//  Copyright © 2017年 SmartHome. All rights reserved.
//

#import "KNBaseAPIRequest.h"
#import "UIApplication+KNAddtions.h"
#import "NSDictionary+KNUrlEncoding.h"
#import "NSString+KNAddtion.h"
#import "KNNetworkingManager.h"

#import "KNMacroFunctions.h"
#import "objc/runtime.h"

@interface KNBaseAPIRequest () <MBProgressHUDDelegate>

@end

@implementation KNBaseAPIRequest
static NSString *autoParmsIdenitifier = @"auto_parms_";

+ (KNBaseAPIRequest *)createRequestWithMethod:(KNRequestMethod)method url:(NSString *)url parms:(id)parms {
    KNBaseAPIRequest *api = [[KNBaseAPIRequest alloc] init];
    api.autoBuildParms = NO;
    api.requestUrl = url;
    api.requestMethod = method;
    api.parmeters = parms;
    api.needShowRequestHud = NO;
    api.needShowRequestFaildMsg = NO;
    api.userInteractionEnabled = NO;
    api.requestSerilizer = KNRequestSerializerPlainText;
    api.timeout = 10;
    api.errorText = @"网络不太稳定呦~~";
    return api;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.requestMethod = KNRequestMethodGET;
        self.timeout = 60;
        self.parmeters = @{};
        self.requestSerilizer = KNRequestSerializerJSON;
        self.responseSerializer = KNResponseSerializerJSON;
        self.needShowRequestHud = YES;
        self.needShowRequestFaildMsg = YES;
        self.hudText = @"请稍等";
        self.hudMode = MBProgressHUDModeIndeterminate;
        self.autoBuildParms = YES;
    }
    return self;
}

- (id)commonParmeters {
    if (_commonParmeters) {
        return _commonParmeters;
    }
    return _commonParmeters = @{@"systemVersion":@([UIApplication KNGetIOSVersion]),
                                     @"productVersion":[UIApplication KNVersionBuild],
                                     @"platform":@"1",
                                     }.mutableCopy;
}

- (NSMutableDictionary *)headers {
    if (_headers) {
        return _headers;
    }

    return nil;
}

- (void)cancel {
    [self.currentTask cancel];
}

- (NSURLSessionDataTask *)uploadFile:(NSData *)data fileName:(NSString *)fileName mimeType:(NSString *)mimeType success:(KNNetworkingSuccess)success faild:(KNNetworkingError)faild {
    [self configManager];
    MBProgressHUD *hud=nil;
    if (self.needShowRequestHud) {
        hud = [self createHUD];
        [hud showAnimated:YES];
    }
    NSMutableDictionary *parms = @{}.mutableCopy;
    if (self.autoBuildParms) {
        // 如果没有参数并且准备使用自动填充参数
        [self setRequestParms];
    }
    
    if ([self.parmeters isKindOfClass:[NSDictionary class]]) {
        [self.parmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
        [self.commonParmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
    } else {
        parms = self.parmeters;
    }
    if ([self.requestUrl containsString:@"?"]) {
        self.requestUrl = [NSString stringWithFormat:@"%@&%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
    } else {
        self.requestUrl = [NSString stringWithFormat:@"%@?%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
    }
    
    return [KNNetworkingManager UPLOAD:self.requestUrl parameters:self.parmeters uploadFile:data uploadFileName:fileName mimeType:mimeType progress:^(NSProgress *downloadProgress) {
        
    } success:^(id result, NSURLResponse *response) {
        [self processResult:result response:response successBlock:success faild:faild hud:hud];
    } failure:^(NSError *errorInfo, NSURLResponse *response) {
        [self processError:errorInfo response:response faild:faild hud:hud];
    }];
}

- (NSURLSessionTask *)downloadFileWithProgress:(void (^)(NSProgress *))progress
                       destination:(NSURL *(^)(NSURL * _Nonnull, NSURLResponse * _Nonnull))destination success:(KNNetworkingSuccess)success failure:(KNNetworkingError)failure {
    [self configManager];
    MBProgressHUD *hud=nil;
    if (self.needShowRequestHud) {
        hud = [self createHUD];
        [hud showAnimated:YES];
    }
    NSMutableDictionary *parms = @{}.mutableCopy;
    if (self.autoBuildParms) {
        // 如果没有参数并且准备使用自动填充参数
        [self setRequestParms];
    }
    
    if ([self.parmeters isKindOfClass:[NSDictionary class]]) {
        [self.parmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
        [self.commonParmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
    } else {
        parms = self.parmeters;
    }
    if ([self.requestUrl containsString:@"?"]) {
        self.requestUrl = [NSString stringWithFormat:@"%@&%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
    } else {
        self.requestUrl = [NSString stringWithFormat:@"%@?%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
    }
    
    return [KNNetworkingManager downloadFile:self.requestUrl progress:progress destination:destination success:^(id result, NSURLResponse *response) {
        if (self.needShowRequestHud) {
            [hud hideAnimated:YES];
        }
        success ? success(result, response) : nil;
    } failure:^(NSError *errorInfo, NSURLResponse *response) {
        [self processError:errorInfo response:response faild:failure hud:hud];
    }];
}


- (NSURLSessionDataTask *)requestWithSuccess:(KNNetworkingSuccess)success faild:(KNNetworkingError)faild {
    [self configManager];
    MBProgressHUD *hud=nil;
    if (self.needShowRequestHud && NSThread.currentThread == NSThread.mainThread) {
        hud = [self createHUD];
        [hud showAnimated:YES];
    }
    NSMutableDictionary *parms = @{}.mutableCopy;
    if (self.autoBuildParms) {
        // 如果没有参数并且准备使用自动填充参数
        [self setRequestParms];
    }
    
    if ([self.parmeters isKindOfClass:[NSDictionary class]]) {
        [self.parmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
        [self.commonParmeters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parms setObject:obj forKey:key];
        }];
    } else {
        parms = self.parmeters;
    }
    
    if (self.requestMethod == KNRequestMethodGET) {
        return [KNNetworkingManager GET:self.requestUrl parameters:parms progress:^(NSProgress *downloadProgress) {
            
        } success:^(id result, NSURLResponse *response) {
            [self processResult:result response:response successBlock:success faild:faild hud:hud];
        } failure:^(NSError *errorInfo, NSURLResponse *response) {
            [self processError:errorInfo response:response faild:faild hud:hud];
        }];
    } else if (self.requestMethod == KNRequestMethodPOST) {
        NSMutableDictionary *commonParams = self.commonParmeters;
        for (NSString *key in [commonParams allKeys]) {
            if ([parms isKindOfClass:[NSDictionary class]] && parms[key]) {
                [parms removeObjectForKey:key];
            }
        }
        if ([self.requestUrl containsString:@"?"]) {
            NSURL *url = [NSURL URLWithString:self.requestUrl];
            NSArray *queryKeyss = [[url.query  KNUrlQueryStringToDict] allKeys];
            for (NSString *key in queryKeyss) {
                if (self.commonParmeters[key]) {
                    [self.commonParmeters removeObjectForKey:key];
                }
            }
            self.requestUrl = [NSString stringWithFormat:@"%@&%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
        } else {
            self.requestUrl = [NSString stringWithFormat:@"%@?%@",self.requestUrl,[self.commonParmeters KNUrlEncodedString]];
        }
        return [KNNetworkingManager POST:self.requestUrl parameters:parms progress:^(NSProgress *downloadProgress) {
            
        } success:^(id result, NSURLResponse *response) {
            [self processResult:result response:response successBlock:success faild:faild hud:hud];
        } failure:^(NSError *errorInfo, NSURLResponse *response) {
            [self processError:errorInfo response:response faild:faild hud:hud];
        }];
    }
    return nil;
}

- (void)configManager {
    [KNNetworkingManager setBaseUrl:self.baseUrl];
    [KNNetworkingManager setRequestSerializer:self.requestSerilizer];
    [KNNetworkingManager setResponseSerializer:self.responseSerializer];
    [KNNetworkingManager setTimeout:self.timeout];
    [KNNetworkingManager setCommonHeaders:self.headers];
}


- (KNNetworkStatus)getNetWorkStates {
    KNNetworkStatus status = KNNetworkStatusNone;
    UIApplication *app = [UIApplication sharedApplication];
    NSArray *children  = [[[app valueForKeyPath:@"statusBar"]valueForKeyPath:@"foregroundView"]subviews];
    int netType = 0;
    //获取到网络返回码
    for (id child in children) {
        if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
            //获取到状态栏
            netType = [[child valueForKeyPath:@"dataNetworkType"]intValue];
            
            switch (netType) {
                case 0:
                    //无网模式
                    status = KNNetworkStatusNone;
                    break;
                case 1:
                    //2G
                    status = KNNetworkStatus2G;
                    break;
                case 2:
                    //3G
                    status = KNNetworkStatus3G;
                    break;
                case 3:
                    //4G
                    status = KNNetworkStatus4G;
                    break;
                case 5:
                    //Wi-Fi
                    status = KNNetworkStatusWIFI;
                    break;
                default:
                    break;
            }
        }
    }
    return status;
}

- (NSError *)haveError:(id)response {
    if (![response isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    NSDictionary *result=(id)response;
    NSInteger state=[[result objectForKey:@"status"] integerValue];
    NSInteger code = [[result objectForKey:@"code"] integerValue];
    if (state == 0 || code == 200) {
        return nil;
    } else {
        NSString *msg = self.errorText;
        if ([result objectForKey:@"msg"]) {
            msg = [result objectForKey:@"msg"];
        }
        NSDictionary *userInfo = @{@"message":msg,
                                   @"code":@(state)};
        
        KNDLog(@"%@\n接口地址:%@\n",userInfo,self.requestUrl);
        return [NSError errorWithDomain:@"KNNetworkingDomain" code:state userInfo:userInfo];
    }
    
}


- (void)processResult:(id)result response:(NSURLResponse *)response successBlock:(KNNetworkingSuccess)success faild:(KNNetworkingError)faild hud:(MBProgressHUD *)hud {
    NSError *error = [self haveError:result];
    if (error) {
        faild?faild(error,response):nil;
        if (self.needShowRequestHud) {
            if (self.needShowRequestFaildMsg) {
                NSDictionary *userInfo = error.userInfo;
                hud.label.text = userInfo[@"message"];
                [hud showAnimated:YES];
                [hud hideAnimated:YES afterDelay:1.6];
            } else {
                [hud hideAnimated:YES];
            }
            
        } else if (self.needShowRequestFaildMsg) {
            hud = [self createHUD];
            NSDictionary *userInfo = error.userInfo;
            hud.label.text = userInfo[@"message"];
            [hud showAnimated:YES];
            [hud hideAnimated:YES afterDelay:1.6];
        }
    } else {
        success?success(result,response):nil;
        [hud hideAnimated:YES];
    }
}

- (void)processError:(NSError *)error response:(NSURLResponse *)response faild:(KNNetworkingError)faild hud:(MBProgressHUD *)hud {
    faild?faild(error,response):nil;
    if (self.needShowRequestHud) {
        if (self.needShowRequestFaildMsg) {
            hud.label.text = self.errorText;
            [hud showAnimated:YES];
            [hud hideAnimated:YES afterDelay:1.6];
        } else {
            [hud hideAnimated:YES];
        }
        
    } else if (self.needShowRequestFaildMsg) {
        hud = [self createHUD];
        hud.label.text = self.errorText;
        [hud showAnimated:YES];
        [hud hideAnimated:YES afterDelay:1.6];
    }
}

- (void)dealloc {
    [self removeHudContainerIfNeed];
}

- (void)setRequestParms
{
    self.parmeters = @{}.mutableCopy;
    NSArray *properties = [[self class] getClassPropertys:[self class]];
    [properties enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
        if ([self valueForKey:obj] && [obj containsString:autoParmsIdenitifier])
        {
            NSString *key = [obj stringByReplacingOccurrencesOfString:autoParmsIdenitifier withString:@""];
            [self.parmeters setObject:[self valueForKey:obj] forKey:key];
        }
    }];
}

- (MBProgressHUD *)createHUD {
    MBProgressHUD *hud = nil;
    if (self.hudContainerView == nil) {
        self.hudContainerView = [[[UIApplication sharedApplication]delegate]window];
    }
    hud = [[MBProgressHUD alloc] initWithView:self.hudContainerView];
    hud.userInteractionEnabled = self.userInteractionEnabled;
    hud.bezelView.color = [[UIColor blackColor] colorWithAlphaComponent:0.9];
    hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
    hud.contentColor = [UIColor whiteColor];
    [self.hudContainerView addSubview:hud];
    hud.label.text = self.hudText;
    hud.mode = self.hudMode;
    hud.removeFromSuperViewOnHide=YES;
    return hud;
}

+ (NSArray *)getClassPropertys:(Class)aClass
{
    NSMutableArray *array = @[].mutableCopy;
    unsigned int count;
    objc_property_t *properties = class_copyPropertyList(aClass, &count);
    for(int i = 0; i < count; i++)
    {
        objc_property_t property = properties[i];
        [array addObject:[NSString stringWithFormat:@"%s",property_getName(property)]];
    }
    free(properties);
    return array;
}

#pragma Mark MBHUDDelegate

-(void)removeHudContainerIfNeed {
    if (self.needRemoveHUDContainerView) {
        [self.hudContainerView removeFromSuperview];
    }
}

@end
